package com.example.rabc.service.impl;

import com.example.rabc.dao.RoleRepository;
import com.example.rabc.dao.UserRepository;
import com.example.rabc.exception.BusinessException;
import com.example.rabc.entity.Role;
import com.example.rabc.entity.User;
import com.example.rabc.monitor.Monitored;
import com.example.rabc.service.ExternalAuthService;
import com.example.rabc.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 */
@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

//    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Autowired
    private  PasswordEncoder passwordEncoder;

    // 注入外部认证服务适配器（可为空）
    @Autowired(required = false)
    private ExternalAuthService externalAuthService;

    /**
     * 创建用户
     * @param user 用户实体
     * @param roleCodes 角色代码列表
     * @return 创建的用户实体
     */
    @Override
    @Monitored
    public User createUser(User user, Set<String> roleCodes) {
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new BusinessException("用户名已存在");
        }

        // 检查邮箱是否存在
        if (user.getEmail() != null && userRepository.existsByEmail(user.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }

        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 设置角色
        if (roleCodes != null && !roleCodes.isEmpty()) {
            Set<Role> roles = roleCodes.stream()
                    .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                            .orElseThrow(() -> new BusinessException("角色不存在: " + roleCode)))
                    .collect(Collectors.toSet());
            user.setRoles(roles);
        }

        return userRepository.save(user);
    }

    /**
     * 更新用户
     * @param userId 用户ID
     * @param user 用户实体
     * @param roleCodes 角色代码列表
     * @return 更新后的用户实体
     */
    @Override
    @Monitored
    public User updateUser(Long userId, User user, Set<String> roleCodes) {
        User existingUser = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        // 更新用户信息
        existingUser.setEmail(user.getEmail());
        existingUser.setRealName(user.getRealName());
        existingUser.setStatus(user.getStatus());

        // 更新角色
        if (roleCodes != null) {
            Set<Role> roles = roleCodes.stream()
                    .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                            .orElseThrow(() -> new BusinessException("角色不存在: " + roleCode)))
                    .collect(Collectors.toSet());
            existingUser.getRoles().clear();
            existingUser.getRoles().addAll(roles);
        }

        return userRepository.save(existingUser);
    }

    /**
     * 删除用户
     * @param userId 用户ID
     */
    @Override
    @Monitored
    public void deleteUser(Long userId) {
        if (!userRepository.existsById(userId)) {
            throw new BusinessException("用户不存在");
        }
        userRepository.deleteById(userId);
    }

    /**
     * 根据ID获取用户
     * @param userId 用户ID
     * @return 用户实体
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public User getUserById(Long userId) {
        return userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));
    }

    /**
     * 根据用户名获取用户
     * @param username 用户名
     * @return 用户实体
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new BusinessException("用户不存在"));
    }

    /**
     * 获取所有用户
     * @return 用户实体列表
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

     /**
     * 根据角色获取用户列表
     * @param roleCode 角色代码
     * @return 用户实体列表
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public List<User> getUsersByRole(String roleCode) {
        Role role = roleRepository.findByRoleCode(roleCode)
                .orElseThrow(() -> new BusinessException("角色不存在"));
        return userRepository.findAll().stream()
                .filter(user -> user.getRoles().contains(role))
                .collect(Collectors.toList());
    }

     /**
     * 为用户分配角色
     * @param userId 用户ID
     * @param roleCodes 角色代码列表
     * @return 是否分配成功
     */
    @Override
    @Monitored
    public boolean assignRolesToUser(Long userId, Set<String> roleCodes) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        Set<Role> roles = roleCodes.stream()
                .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                        .orElseThrow(() -> new BusinessException("角色不存在: " + roleCode)))
                .collect(Collectors.toSet());

        user.getRoles().addAll(roles);
        userRepository.save(user);
        return true;
    }

     /**
     * 从用户移除角色
     * @param userId 用户ID
     * @param roleCodes 角色代码列表
     * @return 是否移除成功
     */
    @Override
    @Monitored
    public boolean removeRolesFromUser(Long userId, Set<String> roleCodes) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        Set<Role> rolesToRemove = roleCodes.stream()
                .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                        .orElseThrow(() -> new BusinessException("角色不存在: " + roleCode)))
                .collect(Collectors.toSet());

        user.getRoles().removeAll(rolesToRemove);
        userRepository.save(user);
        return true;
    }


    /**
     * 使用外部认证服务验证用户
     * @param username 用户名
     * @param password 密码
     * @return 是否验证成功
     */
    @Override
    @Monitored
    public boolean authenticateWithExternalService(String username, String password) {
        // 如果没有配置外部认证服务，则返回false
        if (externalAuthService == null) {
            log.info("No external auth service configured, using local authentication");
            return false;
        }

        try {
            log.info("Authenticating user {} with external service", username);
            return externalAuthService.authenticate(username, password);
        } catch (Exception e) {
            log.error("Error during external authentication for user: {}", username, e);
            return false;
        }
    }

    /**
     * 从外部服务同步用户角色
     * @param username 用户名
     * @return 是否同步成功
     */
    @Override
    @Monitored
    public boolean syncUserRolesFromExternalService(String username) {
        // 如果没有配置外部认证服务，则返回false
        if (externalAuthService == null) {
            log.info("No external auth service configured, cannot sync roles");
            return false;
        }

        try {
            log.info("Syncing roles for user {} from external service", username);

            // 获取用户角色
            Set<String> externalRoles = externalAuthService.getUserRoles(username);

            // 获取或创建用户实体
            User user = userRepository.findByUsername(username)
                    .orElseGet(() -> {
                        log.info("User {} does not exist, creating new user", username);
                        User newUser = new User();
                        newUser.setUsername(username);
                        // 为OAuth用户生成一个随机密码，因为OAuth用户不会使用这个密码登录
                        newUser.setPassword(passwordEncoder.encode(username + System.currentTimeMillis()));
                        newUser.setEmail(username + "@oauth.github.com"); // 为OAuth用户设置默认邮箱
                        newUser.setRealName(username); // 为OAuth用户设置默认真实姓名
                        newUser.setStatus(1); // 设置用户状态为激活
                        return userRepository.save(newUser);
                    });

            // 清空现有角色并添加外部服务提供的角色
            user.getRoles().clear();

            if (externalRoles != null && !externalRoles.isEmpty()) {
                Set<Role> roles = externalRoles.stream()
                        .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                                .orElse(null)) // 如果角色不存在，返回null
                        .filter(role -> role != null) // 过滤掉不存在的角色
                        .collect(Collectors.toSet());

                user.getRoles().addAll(roles);
            }

            // 保存用户
            userRepository.save(user);
            log.info("Successfully synced roles for user {}", username);
            return true;
        } catch (Exception e) {
            log.error("Error during syncing roles from external service for user: {}", username, e);
            return false;
        }
    }
}